package com.suny.sf_server.service.impl;
import com.suny.Fence.dto.FenceAddDTO;
import com.suny.Fence.dto.FenceUpdateDTO;
import com.suny.Fence.vo.FenceVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suny.constant.RedisKeyConstant;
import com.suny.result.ResponseCode;
import com.suny.sf_server.redis.IRedisService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import com.suny.Farm.domain.Farm;
import com.suny.Fence.domain.Fence;
import com.suny.sf_server.service.FenceService;
import com.suny.sf_server.mapper.FenceMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.suny.sf_server.service.PenService;
import com.suny.sf_server.service.FarmService;

import com.suny.Pen.domain.Pen;
import com.suny.exception.BusinessException;
import com.suny.result.PageDTO;
import com.suny.Fence.dto.FenceQueryDTO;


/**
 * @author sun
 * @description 针对表【fence(围栏管理表)】的数据库操作Service实现
 * @createDate 2024-12-27 10:45:10
 */
@Service
@Slf4j
public class FenceServiceImpl extends ServiceImpl<FenceMapper, Fence> implements FenceService {

    @Resource
    private PenService penService;

    @Resource
    private FarmService farmService;

    @Resource
    private IRedisService redisService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(FenceAddDTO dto) {
        // 验证牧场是否存在且启用
        Farm farm = farmService.getById(dto.getFarmId());
        if (farm == null || farm.getStatus() != 1) {
            throw new BusinessException("牧场不存在或未启用");
        }

        // 验证圈舍是否存在且启用
        Pen pen = penService.getById(dto.getPenId());
        if (pen == null || pen.getStatus() != 1) {
            throw new BusinessException("圈舍不存在或未启用");
        }

        // 验证围栏名称在同一圈舍下是否重复
        checkFenceNameExists(dto.getPenId(), dto.getFenceName(), null);

        // 保存围栏信息
        Fence fence = new Fence();
        fence.setPenId(dto.getPenId());
        fence.setFarmId(dto.getFarmId());
        fence.setFenceName(dto.getFenceName());
        fence.setAmountLivestock(0);
        fence.setStatus(1);
        fence.setCreateTime(new Date());
        fence.setUpdateTime(new Date());

        save(fence);

        // 清除相关缓存
        clearCache(dto.getPenId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(FenceUpdateDTO dto) {
        // 验证围栏是否存在
        Fence fence = getById(dto.getFenceId());
        if (fence == null) {
            throw new BusinessException("围栏不存在");
        }

        // 验证圈舍是否存在且启用
        Pen pen = penService.getById(dto.getPenId());
        if (pen == null || pen.getStatus() != 1) {
            throw new BusinessException("圈舍不存在或未启用");
        }

        // 验证围栏名称在同一圈舍下是否重复
        checkFenceNameExists(dto.getPenId(), dto.getFenceName(), dto.getFenceId());

        // 更新围栏信息
        fence.setPenId(dto.getPenId());
        fence.setFenceName(dto.getFenceName());
        fence.setUpdateTime(new Date());

        updateById(fence);

        // 清除相关缓存
        clearCache(fence.getPenId());
        // 如果圈舍发生变化，也要清除原圈舍的缓存
        if (!fence.getPenId().equals(dto.getPenId())) {
            clearCache(dto.getPenId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Integer fenceId, Integer status) {
        if (fenceId == null || status == null) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        if (status != 1 && status != 0) {
            throw new BusinessException("状态值无效");
        }
        Fence fence = getById(fenceId);
        if (fence == null) {
            throw new BusinessException("围栏不存在");
        }
        if (Objects.equals(fence.getStatus(), status)) {
            throw new BusinessException("状态值未改变");
        }

        // 如果要停用，检查是否有未出栏牲畜
        if (status == 0 && fence.getAmountLivestock() > 0) {
            throw new BusinessException("围栏内还有未出栏牲畜，不能停用");
        }

        fence.setStatus(status);
        fence.setUpdateTime(new Date());
        updateById(fence);

        // 清除相关缓存
        clearCache(fence.getPenId());
    }

    @Override
    public Page<FenceVO> getList(PageDTO pageDTO) {
        // 1. 参数校验
        if (pageDTO == null || pageDTO.getPageNumber() <= 0 || pageDTO.getPageSize() <= 0) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        
        // 2. 生成包含分页参数的缓存key
        String cacheKey = String.format("%s:%d:%d", 
            RedisKeyConstant.FENCE_LIST,
            pageDTO.getPageNumber(),
            pageDTO.getPageSize());
        
        // 3. 尝试从缓存获取
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        // 4. 查询数据库
        Page<Fence> page = new Page<>(pageDTO.getPageNumber(), pageDTO.getPageSize());
        IPage<FenceVO> voPage = baseMapper.selectFenceVOPage(page);
        
        // 5. 处理空结果缓存
        if (voPage != null && voPage.getTotal() > 0) {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.CACHE_TIME);
        } else {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.EMPTY_CACHE_TIME);
        }
        
        return (Page<FenceVO>) voPage;
    }

    @Override
    public List<FenceVO> getEnableFencesByPenId(Integer penId) {
        // 1. 参数校验
        if (penId == null || penId <= 0) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        
        // 2. 生成缓存key
        String cacheKey = RedisKeyConstant.FENCE_PEN_PREFIX + penId;
        
        // 3. 尝试从缓存获取
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        // 4. 查询数据库
        List<FenceVO> list = baseMapper.selectEnableFencesByPenId(penId);
        
        // 5. 处理空结果缓存
        if (list != null && !list.isEmpty()) {
            redisService.setValue(cacheKey, list, RedisKeyConstant.CACHE_TIME);
        } else {
            redisService.setValue(cacheKey, list, RedisKeyConstant.EMPTY_CACHE_TIME);
        }
        
        return list;
    }

    @Override
    public Page<FenceVO> getListByCondition(FenceQueryDTO query) {
        // 添加日志打印查看参数
        log.info("查询参数: {}", query);
        
        // 1. 参数校验
        if (query == null || query.getPageSize() == null || query.getPageSize() <= 0) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        
        // 2. 生成包含查询条件的缓存key
        String cacheKey = String.format("%s:%s:%d:%d", 
            RedisKeyConstant.FENCE_LIST,
            query.hashCode(),
            query.getPageNumber(),
            query.getPageSize());
        
        // 3. 尝试从缓存获取
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        // 4. 查询数据库
        Page<Fence> page = new Page<>(query.getPageNumber(), query.getPageSize());

        IPage<FenceVO> voPage = baseMapper.selectFenceVOPageByCondition(page, query);
        
        // 5. 处理空结果缓存
        if (voPage != null && voPage.getTotal() > 0) {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.CACHE_TIME);
        } else {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.EMPTY_CACHE_TIME);
        }
        
        return (Page<FenceVO>) voPage;
    }

    private void checkFenceNameExists(Integer penId, String fenceName, Integer excludeFenceId) {
        LambdaQueryWrapper<Fence> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Fence::getPenId, penId)
                .eq(Fence::getFenceName, fenceName);

        if (excludeFenceId != null) {
            wrapper.ne(Fence::getFenceId, excludeFenceId);
        }

        if (count(wrapper) > 0) {
            throw new BusinessException("该圈舍下已存在同名围栏");
        }
    }

    /**
     * 清除围栏相关缓存
     */
    private void clearCache(Integer penId) {
        // 使用模式匹配删除所有围栏列表缓存
        redisService.removePattern(RedisKeyConstant.FENCE_LIST + ":*");
        redisService.remove(RedisKeyConstant.FENCE_PEN_PREFIX + penId);
    }
}




